package com.example.myjavafx.controller;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;

import java.io.ByteArrayInputStream;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Base64;

public class CameraController {
    @FXML
    private TextField exposureTime;
    @FXML
    private TextField gain;
    @FXML
    private TextField serialNumber;
    @FXML private TextField deviceAddressField;
    @FXML private Label connectionStatusLabel;
    @FXML private TextArea paramConfigArea;
    @FXML private TextArea responseTextArea;
    @FXML private ImageView capturedImageView;

    private HttpClient httpClient;
    private Gson gson;
    private final HttpClient client = HttpClient.newHttpClient();

    String baseUrl = "http://192.168.0.173:12345/api/control";
    /**
     * 初始化方法，用于设置默认参数配置。
     */
    public void initialize() {
        httpClient = HttpClient.newHttpClient();
        gson = new Gson();

        // 预设一些默认参数配置
        paramConfigArea.setText(getDefaultCameraParams());
    }

    /**
     * 获取默认的相机参数配置。
     * @return 默认参数配置的JSON字符串。
     */
    private String getDefaultCameraParams() {
        JsonObject defaultParams = new JsonObject();
        defaultParams.addProperty("resolution", "1920x1080");
        defaultParams.addProperty("exposure", "auto");
        defaultParams.addProperty("gain", "medium");
        return gson.toJson(defaultParams);
    }

    /**
     * 初始化
     */

    @FXML
    private void initializeCamera() {

        JsonObject defaultParams = new JsonObject();
        defaultParams.addProperty("class_name", "MVCameraControl");
        defaultParams.addProperty("mode", "initialize");
        defaultParams.addProperty("function_name", "055041220579");
//        sendPostRequest("/camera/init", parseParamConfig());
        sendPostRequest("/camera/init", defaultParams);
    }

    /**
     * 打开相机
     */
    @FXML
    private void openCamera() {
        JsonObject defaultParams = new JsonObject();
        defaultParams.addProperty("class_name", "MVCameraControl");
        defaultParams.addProperty("mode", "invoking");
        defaultParams.addProperty("function_name", "turn_on");
        defaultParams.addProperty("exposure_time", 30);
        defaultParams.addProperty("gain", 100);
        defaultParams.addProperty("trigger_mode", 1);
        sendPostRequest("/camera/open", defaultParams);
    }

    /***
     * 采图
     */
    @FXML
    private void captureImage() {
//        sendPostRequest2("/camera/capture", parseParamConfig());
        sendPostRequest("/camera/capture", parseParamConfig());
    }

    private void sendPostRequest2(String path, JsonObject jsonObject) {


        Task<Image> task = new Task<>() {
            @Override
            protected Image call() throws Exception {
                JsonObject requestBody = new JsonObject();
                requestBody.addProperty("mode", "invoking");
                requestBody.addProperty("class_name", "MVCameraControl");
                requestBody.addProperty("function_name", "capture");
                requestBody.addProperty("timeout", 200);

                HttpRequest request = HttpRequest.newBuilder()
                        .header("Content-Type", "application/json")
                        .uri(URI.create("http://192.168.0.173:12345/api/control"))
                        .POST(HttpRequest.BodyPublishers.ofString(requestBody.toString()))
                        .build();


                HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
                String json = response.body();

                // 解析JSON获取Base64图像数据
                ObjectMapper mapper = new ObjectMapper();
                JsonNode node = mapper.readTree(json);
                String base64Image = node.get("data").asText();

                // 解码Base64为字节数组
                byte[] imageData = Base64.getDecoder().decode(base64Image);
                return new Image(new ByteArrayInputStream(imageData));
            }
        };

        task.setOnSucceeded(e -> capturedImageView.setImage(task.getValue()));
        task.setOnFailed(e -> showError("加载失败: " + task.getException().getMessage()));

        new Thread(task).start();

    }

    /**
     * 关闭相机
     */
    @FXML
    private void closeCamera() {

        JsonObject defaultParams = new JsonObject();
        defaultParams.addProperty("class_name", "MVCameraControl");
        defaultParams.addProperty("mode", "invoking");
        defaultParams.addProperty("function_name", "turn_off");
        defaultParams.addProperty("exposure_time", 30);
        defaultParams.addProperty("gain", 100);
        defaultParams.addProperty("trigger_mode", 1);
        sendPostRequest("/camera/close", defaultParams);
    }

    /**
     * 解析参数配置文本框中的JSON字符串。
     * @return 解析后的JsonObject对象。如果JSON格式错误，将显示一个警告并返回空JsonObject。
     */
    private JsonObject parseParamConfig() {
        try {
            return JsonParser.parseString(paramConfigArea.getText()).getAsJsonObject();
        } catch (Exception e) {
            showAlert("参数错误", "请检查JSON参数格式");
            return new JsonObject();
        }
    }

    private void sendPostRequest(String endpoint, JsonObject requestBody) {
//        String baseUrl = deviceAddressField.getText();
//        if (baseUrl.isEmpty()) {
//            showAlert("错误", "请先输入设备地址");
//            return;
//        }

        try {
            HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create(baseUrl))
                    .header("Content-Type", "application/json")
                    .POST(HttpRequest.BodyPublishers.ofString(requestBody.toString()))
                    .build();

            httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString())
                    .thenAccept(response -> Platform.runLater(() -> {
                        int statusCode = response.statusCode();
                        String responseBody = response.body();
                        updateUIWithResponse(statusCode, responseBody);
                    })).exceptionally(throwable -> {
                        // 请求异常，显示错误信息
                        responseTextArea.setText("请求异常: " + throwable.getMessage());
//                        showAlert("错误", "请求异常: " + throwable.getMessage());
                        return null;
                    });
        } catch (Exception e) {
            // 请求发送失败，显示错误信息
            responseTextArea.setText("请求发送失败: " + e.getMessage());
//            showAlert("错误", "请求发送失败: " + e.getMessage());
        }
    }

    private void updateUIWithResponse(int statusCode, String responseBody) {
        responseTextArea.setText("状态码: " + statusCode + "\n响应内容: " + responseBody);

        try {
            JsonObject jsonResponse = gson.fromJson(responseBody, JsonObject.class);

            // 更新连接状态
            if (jsonResponse.has("message")) {
                connectionStatusLabel.setText(jsonResponse.get("status").getAsString());
            }

            // 处理图像数据
            if (jsonResponse.has("image")) {
                String base64Image = jsonResponse.get("image").getAsString();
                byte[] imageBytes = Base64.getDecoder().decode(base64Image);
                Image image = new Image(new ByteArrayInputStream(imageBytes));
                capturedImageView.setImage(image);
            }
        } catch (Exception e) {
            // JSON解析失败，不做处理
        }
    }

    private void showAlert(String title, String content) {
        Alert alert = new Alert(Alert.AlertType.INFORMATION);
        alert.setTitle(title);
        alert.setHeaderText(null);
        alert.setContentText(content);
        alert.showAndWait();
    }
    private void showError(String message) {
        Platform.runLater(() -> {
            Alert alert = new Alert(Alert.AlertType.ERROR);
            alert.setContentText(message);
            alert.show();
        });
    }
}